/* drv_uart_int.c */
#include "app_inc.h"

#define DRV_UART_BUFFER_SIZE    16U
uint8_t gDrvUartTxBuffer[DRV_UART_BUFFER_SIZE];
uint8_t gDrvUartRxBuffer[DRV_UART_BUFFER_SIZE];
RBUF_Handler_T gDrvUartTxBufStruct;
RBUF_Handler_T gDrvUartRxBufStruct;
volatile bool gDrvEnTxBufEmptyInterrupt;

void DRV_UART_InitAddWithIntMode(void)
{
    /* Init the Tx/Rx buffer. */
    RBUF_Init(&gDrvUartTxBufStruct, gDrvUartTxBuffer, DRV_UART_BUFFER_SIZE);
    RBUF_Init(&gDrvUartRxBufStruct, gDrvUartRxBuffer, DRV_UART_BUFFER_SIZE);

    /* Wait for the hardware FIFO to be cleared. */
    /* The software must wait until TC=1. The TC flag remains cleared during all data
     * transfers and it is set by hardware at the last frame end of transmission.
     */
    while (USART_GetBitState(DRV_UART_INSTANCE, USART_FLAG_TC) == RESET)
    {}

    /* Configure the UART interrupt. */
    /* Enable the USARTx Transmoit interrupt
     * This interrupt is generated when the USARTx transmit data register is empty.
     */  
    /* USART_INT_Set(DRV_UART_INSTANCE, USART_INT_TBE, ENABLE); */
    USART_INT_Set(DRV_UART_INSTANCE, USART_INT_TBE, DISABLE); /* Disable Tx buffer empty interrupt. */
    gDrvEnTxBufEmptyInterrupt = false;
    /* Enable the USARTx Receive interrupt
     * This interrupt is generated when the USARTx receive data register is not empty.
     */
    USART_INT_Set(DRV_UART_INSTANCE, USART_INT_RBNE, ENABLE); /* Enable Rx buffer available interrupt. */

    /* Configure the NVIC. */
    NVIC_EnableIRQ(DRV_UART_IRQ_ID);
}

void DRV_UART_PutCharWithIntMode(uint8_t ch)
{
    while (RBUF_IsFull(&gDrvUartTxBufStruct))
    {}
    RBUF_PutDataIn(&gDrvUartTxBufStruct, ch);
    if (!gDrvEnTxBufEmptyInterrupt)
    {
        gDrvEnTxBufEmptyInterrupt = true;
        USART_INT_Set(DRV_UART_INSTANCE, USART_INT_TBE, ENABLE);
    }
}

uint8_t DRV_UART_GetCharWithIntMode(void)
{
    while (RBUF_IsEmpty(&gDrvUartRxBufStruct))
    {}
    return RBUF_GetDataOut(&gDrvUartRxBufStruct);
}

/* System defined vector for USART0 ISR. */
void DRV_UART_IRQ_HANDLER_FUNC(void)
{
    uint8_t tmp8;

    /* Rx Process. */
    if(USART_GetIntBitState( DRV_UART_INSTANCE, USART_INT_RBNE) != RESET)
    {
        tmp8 = (uint8_t)(USART_DataReceive(DRV_UART_INSTANCE) & 0x7F); /* Read Rx buffer to clear the flag. */
        if (!RBUF_IsFull(&gDrvUartRxBufStruct))
        {
            RBUF_PutDataIn(&gDrvUartRxBufStruct, tmp8);
        }
    }
    /* Tx Process. */
    if( gDrvEnTxBufEmptyInterrupt && (USART_GetIntBitState(DRV_UART_INSTANCE, USART_INT_TBE) != RESET) )
    {
        USART_DataSend(DRV_UART_INSTANCE, RBUF_GetDataOut(&gDrvUartTxBufStruct));
        if (RBUF_IsEmpty(&gDrvUartTxBufStruct))
        {
            USART_INT_Set(DRV_UART_INSTANCE, USART_INT_TBE, DISABLE);
            gDrvEnTxBufEmptyInterrupt = false;
        }
    }
}

/* EOF. */
